Spawn vncviewer from qemu-dm.
authorchris@kneesaa.uk.xensource.com <chris@kneesaa.uk.xensource.com>
Fri, 14 Jul 2006 17:53:27 +0000 (18:53 +0100)
committerchris@kneesaa.uk.xensource.com <chris@kneesaa.uk.xensource.com>
Fri, 14 Jul 2006 17:53:27 +0000 (18:53 +0100)
- add vncviewer option to qemu-dm to spawn a vncviewer process.
- add the `vncconsole' config parameter which enables qemu-dm's vncviewer
  option.

Based on a patch from: Don Dugger <donald.d.dugger@intel.com>
Signed-off-by: Christian Limpach <Christian.Limpach@xensource.com>
tools/examples/xmexample.hvm
tools/ioemu/patches/series
tools/ioemu/patches/vnc-start-vncviewer [new file with mode: 0644]
tools/ioemu/vl.c
tools/ioemu/vl.h
tools/ioemu/vnc.c
tools/python/xen/xend/image.py
tools/python/xen/xm/create.py

index 7ec80b9bad9476c93fd4e5026f5b399124d450af..2d2eef873543dd16632483302001d26f289f0e30 100644 (file)
@@ -134,8 +134,9 @@ vnc=1
 #vncdisplay=1
 
 #----------------------------------------------------------------------------
-# enable spawning vncviewer(only valid when vnc=1), default = 1
-vncviewer=1
+# enable spawning vncviewer for domain's console
+# (only valid when vnc=1), default = 0
+#vncconsole=0
 
 #----------------------------------------------------------------------------
 # no graphics, use serial port
index 3c3c025cce0a7908a45fba73d784fbab52680c24..351adf73d908817a3b86b014997aa9151c1ef329 100644 (file)
@@ -30,3 +30,4 @@ acpi-timer-support
 acpi-poweroff-support
 vnc-cleanup
 vnc-fixes
+vnc-start-vncviewer
diff --git a/tools/ioemu/patches/vnc-start-vncviewer b/tools/ioemu/patches/vnc-start-vncviewer
new file mode 100644 (file)
index 0000000..944e263
--- /dev/null
@@ -0,0 +1,105 @@
+Index: ioemu/vnc.c
+===================================================================
+--- ioemu.orig/vnc.c   2006-07-14 18:29:36.810169908 +0100
++++ ioemu/vnc.c        2006-07-14 18:30:17.437628819 +0100
+@@ -999,3 +999,25 @@
+     vnc_dpy_resize(vs->ds, 640, 400);
+ }
++
++int vnc_start_viewer(int port)
++{
++    int pid;
++    char s[16];
++
++    sprintf(s, ":%d", port);
++
++    switch (pid = fork()) {
++    case -1:
++      fprintf(stderr, "vncviewer failed fork\n");
++      exit(1);
++
++    case 0:   /* child */
++      execlp("vncviewer", "vncviewer", s, 0);
++      fprintf(stderr, "vncviewer execlp failed\n");
++      exit(1);
++
++    default:
++      return pid;
++    }
++}
+Index: ioemu/vl.c
+===================================================================
+--- ioemu.orig/vl.c    2006-07-14 18:29:36.809170020 +0100
++++ ioemu/vl.c 2006-07-14 18:30:17.435629043 +0100
+@@ -121,6 +121,7 @@
+ int bios_size;
+ static DisplayState display_state;
+ int nographic;
++int vncviewer;
+ const char* keyboard_layout = NULL;
+ int64_t ticks_per_sec;
+ int boot_device = 'c';
+@@ -4801,6 +4802,7 @@
+ #endif
+            "-loadvm file    start right away with a saved state (loadvm in monitor)\n"
+          "-vnc display    start a VNC server on display\n"
++           "-vncviewer      start a vncviewer process for this domain\n"
+            "-timeoffset     time offset (in seconds) from local time\n"
+            "\n"
+            "During emulation, the following keys are useful:\n"
+@@ -4889,6 +4891,7 @@
+     QEMU_OPTION_usbdevice,
+     QEMU_OPTION_smp,
+     QEMU_OPTION_vnc,
++    QEMU_OPTION_vncviewer,
+     QEMU_OPTION_d,
+     QEMU_OPTION_vcpus,
+@@ -4964,6 +4967,7 @@
+     { "usbdevice", HAS_ARG, QEMU_OPTION_usbdevice },
+     { "smp", HAS_ARG, QEMU_OPTION_smp },
+     { "vnc", HAS_ARG, QEMU_OPTION_vnc },
++    { "vncviewer", 0, QEMU_OPTION_vncviewer },
+     
+     /* temporary options */
+     { "usb", 0, QEMU_OPTION_usb },
+@@ -5294,6 +5298,7 @@
+ #endif
+     snapshot = 0;
+     nographic = 0;
++    vncviewer = 0;
+     kernel_filename = NULL;
+     kernel_cmdline = "";
+ #ifdef TARGET_PPC
+@@ -5663,6 +5668,9 @@
+                   exit(1);
+               }
+               break;
++            case QEMU_OPTION_vncviewer:
++                vncviewer++;
++                break;
+             case QEMU_OPTION_domainname:
+                 strncat(domain_name, optarg, sizeof(domain_name) - 20);
+                 break;
+@@ -5881,6 +5889,8 @@
+         dumb_display_init(ds);
+     } else if (vnc_display != -1) {
+       vnc_display_init(ds, vnc_display);
++      if (vncviewer)
++          vnc_start_viewer(vnc_display);
+     } else {
+ #if defined(CONFIG_SDL)
+         sdl_display_init(ds, full_screen);
+Index: ioemu/vl.h
+===================================================================
+--- ioemu.orig/vl.h    2006-07-14 18:29:36.810169908 +0100
++++ ioemu/vl.h 2006-07-14 18:30:17.436628931 +0100
+@@ -732,6 +732,7 @@
+ /* vnc.c */
+ void vnc_display_init(DisplayState *ds, int display);
++int vnc_start_viewer(int port);
+ /* ide.c */
+ #define MAX_DISKS 4
index 3eafd801ee2b88e0a897b81c1e3aed91171ce1a9..58bb34c32b73b129ff97fb46368d3755d8249298 100644 (file)
@@ -121,6 +121,7 @@ int vga_ram_size;
 int bios_size;
 static DisplayState display_state;
 int nographic;
+int vncviewer;
 const char* keyboard_layout = NULL;
 int64_t ticks_per_sec;
 int boot_device = 'c';
@@ -4801,6 +4802,7 @@ void help(void)
 #endif
            "-loadvm file    start right away with a saved state (loadvm in monitor)\n"
           "-vnc display    start a VNC server on display\n"
+           "-vncviewer      start a vncviewer process for this domain\n"
            "-timeoffset     time offset (in seconds) from local time\n"
            "\n"
            "During emulation, the following keys are useful:\n"
@@ -4889,6 +4891,7 @@ enum {
     QEMU_OPTION_usbdevice,
     QEMU_OPTION_smp,
     QEMU_OPTION_vnc,
+    QEMU_OPTION_vncviewer,
 
     QEMU_OPTION_d,
     QEMU_OPTION_vcpus,
@@ -4964,6 +4967,7 @@ const QEMUOption qemu_options[] = {
     { "usbdevice", HAS_ARG, QEMU_OPTION_usbdevice },
     { "smp", HAS_ARG, QEMU_OPTION_smp },
     { "vnc", HAS_ARG, QEMU_OPTION_vnc },
+    { "vncviewer", 0, QEMU_OPTION_vncviewer },
     
     /* temporary options */
     { "usb", 0, QEMU_OPTION_usb },
@@ -5294,6 +5298,7 @@ int main(int argc, char **argv)
 #endif
     snapshot = 0;
     nographic = 0;
+    vncviewer = 0;
     kernel_filename = NULL;
     kernel_cmdline = "";
 #ifdef TARGET_PPC
@@ -5663,6 +5668,9 @@ int main(int argc, char **argv)
                    exit(1);
                }
                break;
+            case QEMU_OPTION_vncviewer:
+                vncviewer++;
+                break;
             case QEMU_OPTION_domainname:
                 strncat(domain_name, optarg, sizeof(domain_name) - 20);
                 break;
@@ -5881,6 +5889,8 @@ int main(int argc, char **argv)
         dumb_display_init(ds);
     } else if (vnc_display != -1) {
        vnc_display_init(ds, vnc_display);
+       if (vncviewer)
+           vnc_start_viewer(vnc_display);
     } else {
 #if defined(CONFIG_SDL)
         sdl_display_init(ds, full_screen);
index c16a1b64f4f947a6b9e3022ced3b6a0187f6fc4c..f21d0aff8365d4933c8818eafd3e45d3544cc08b 100644 (file)
@@ -732,6 +732,7 @@ void cocoa_display_init(DisplayState *ds, int full_screen);
 
 /* vnc.c */
 void vnc_display_init(DisplayState *ds, int display);
+int vnc_start_viewer(int port);
 
 /* ide.c */
 #define MAX_DISKS 4
index 4a516306cb1bad682480ab2e6c4591de0c523e6a..55407c38f24b27a786b5096d4bf252f53dbfc44c 100644 (file)
@@ -999,3 +999,25 @@ void vnc_display_init(DisplayState *ds, int display)
 
     vnc_dpy_resize(vs->ds, 640, 400);
 }
+
+int vnc_start_viewer(int port)
+{
+    int pid;
+    char s[16];
+
+    sprintf(s, ":%d", port);
+
+    switch (pid = fork()) {
+    case -1:
+       fprintf(stderr, "vncviewer failed fork\n");
+       exit(1);
+
+    case 0:    /* child */
+       execlp("vncviewer", "vncviewer", s, 0);
+       fprintf(stderr, "vncviewer execlp failed\n");
+       exit(1);
+
+    default:
+       return pid;
+    }
+}
index 10c3c37a383cd22c282d89da06788205ee2fa6b3..12606a58bd40c69fe6d66264c091c8c0a39c2d27 100644 (file)
@@ -208,6 +208,7 @@ class HVMImageHandler(ImageHandler):
             raise VmError("hvm: missing device model")
         self.display = sxp.child_value(imageConfig, 'display')
         self.xauthority = sxp.child_value(imageConfig, 'xauthority')
+        self.vncconsole = sxp.child_value(imageConfig, 'vncconsole')
 
         self.vm.storeVm(("image/dmargs", " ".join(self.dmargs)),
                         ("image/device-model", self.device_model),
@@ -335,11 +336,7 @@ class HVMImageHandler(ImageHandler):
             return
         # Execute device model.
         #todo: Error handling
-        # XXX RN: note that the order of args matter!
         args = [self.device_model]
-        vnc = self.vncParams()
-        if len(vnc):
-            args = args + vnc
         args = args + ([ "-d",  "%d" % self.vm.getDomid(),
                   "-m", "%s" % (self.vm.getMemoryTarget() / 1024)])
         args = args + self.dmargs
@@ -348,24 +345,12 @@ class HVMImageHandler(ImageHandler):
             env['DISPLAY'] = self.display
         if self.xauthority:
             env['XAUTHORITY'] = self.xauthority
+        if self.vncconsole:
+            args = args + ([ "-vncviewer" ])
         log.info("spawning device models: %s %s", self.device_model, args)
         self.pid = os.spawnve(os.P_NOWAIT, self.device_model, args, env)
         log.info("device model pid: %d", self.pid)
 
-    def vncParams(self):
-        # see if a vncviewer was specified
-        # XXX RN: bit of a hack. should unify this, maybe stick in config space
-        vncconnect=[]
-        args = self.cmdline
-        if args:
-            arg_list = string.split(args)
-            for arg in arg_list:
-                al = string.split(arg, '=')
-                if al[0] == "VNC_VIEWER":
-                    vncconnect=["-vncconnect", "%s" % al[1]]
-                    break
-        return vncconnect
-
     def destroy(self):
         self.unregister_shutdown_watch();
         import signal
index 4af00f458daf3e18340bb792c0fb388daf9802cf..77b03017728100898dd2565076b148d05eee10e1 100644 (file)
@@ -112,6 +112,12 @@ gopts.var('vncviewer', val='no|yes',
           Only valid when vnc=1.
           """)
 
+gopts.var('vncconsole', val='no|yes',
+          fn=set_bool, default=None,
+          use="""Spawn a vncviewer process for the domain's graphical console.
+          Only valid when vnc=1.
+          """)
+
 gopts.var('name', val='NAME',
           fn=set_value, default=None,
           use="Domain name. Must be unique.")
@@ -625,7 +631,7 @@ def configure_hvm(config_image, vals):
     """
     args = [ 'device_model', 'pae', 'vcpus', 'cdrom', 'boot', 'fda', 'fdb',
              'localtime', 'serial', 'stdvga', 'isa', 'nographic', 'audio',
-             'vnc', 'vncdisplay', 'vncviewer', 'sdl', 'display',
+             'vnc', 'vncdisplay', 'vncconsole', 'sdl', 'display',
              'acpi', 'apic', 'xauthority', 'usb', 'usbdevice' ]
     for a in args:
         if (vals.__dict__[a]):
@@ -854,17 +860,18 @@ def preprocess_vnc(vals):
     """If vnc was specified, spawn a vncviewer in listen mode
     and pass its address to the domain on the kernel command line.
     """
-    if not (vals.vnc and vals.vncviewer) or vals.dryrun: return
-    vnc_display = choose_vnc_display()
-    if not vnc_display:
-        warn("No free vnc display")
-        return
-    print 'VNC=', vnc_display
-    vnc_port = spawn_vnc(vnc_display)
-    if vnc_port > 0:
-        vnc_host = get_host_addr()
-        vnc = 'VNC_VIEWER=%s:%d' % (vnc_host, vnc_port)
-        vals.extra = vnc + ' ' + vals.extra
+    if vals.dryrun: return
+    if vals.vncviewer:
+        vnc_display = choose_vnc_display()
+        if not vnc_display:
+            warn("No free vnc display")
+            return
+        print 'VNC=', vnc_display
+        vnc_port = spawn_vnc(vnc_display)
+        if vnc_port > 0:
+            vnc_host = get_host_addr()
+            vnc = 'VNC_VIEWER=%s:%d' % (vnc_host, vnc_port)
+            vals.extra = vnc + ' ' + vals.extra
     
 def preprocess(vals):
     if not vals.kernel and not vals.bootloader: